#include "connection_loop.hpp"
#include <croco/common_exceptions.hpp>
#include <croco/ssh/ssh.hpp>
#include <croco/os/thread_sync.hpp>
#include <iostream>

namespace csh = croco::ssh;
namespace cip = croco::ip;
namespace cros = croco::os;

void connection_loop(cip::server_tcp& socket, csh::integration& integration)
{
    const bool beVerbose = false;
    csh::interface ssh_if(integration, "id_rsa", "id_dsa", "Welcome to the sample libssh-based server\r\n", cros::select_timeout::second(10), beVerbose);
    ssh_if.accept_connection(socket);
    if(!ssh_if.authenticate())
    {
        throw croco::general_error() << croco::more_info("authentication failure");
    }
    while(true)
    {
        cros::select_fds fds;
        fds.add_read(ssh_if.get_session_fd());
        std::set<cros::native_handle_type> signaled = cros::do_select(fds);
        std::vector<char> buffer(1024);
        int recv = ssh_if.receive(&buffer[0], buffer.size());
        if(recv < 0)
        {
            break;
        }
        int sent = ssh_if.send(&buffer[0], static_cast<std::size_t>(recv));
        if(sent < 0)
        {
            break;
        }
        assert(recv == sent);
    }
    std::cout << "connection loop finished" << std::endl;
}

void connection_thread(cip::server_tcp& socket, cros::thread_sync& sync, csh::integration& integration, const std::vector<int>& terms)
{
    try
    {
        const bool beVerbose = false;
        csh::interface ssh_if(integration, "id_rsa", "id_dsa", "Welcome to the sample libssh-based server\r\n", cros::select_timeout::second(10), beVerbose);
        ssh_if.accept_connection(socket);
        sync.signal_started();

        if(!ssh_if.authenticate(terms))
        {
            throw croco::general_error() << croco::more_info("authentication failure");
        }
        while(true)
        {
            cros::select_fds fds;
            fds.add_read(ssh_if.get_session_fd());
            for(std::size_t i = 0, end = terms.size(); i < end; i++)
            {
                fds.add_interrupt(terms[i]);
            }
            std::set<cros::native_handle_type> signaled = cros::do_select(fds);
            if(fds.interrupted(signaled))
            {
                std::cout << "stopping connection loop - server stop requested" << std::endl;
                break;
            }

            std::vector<char> buffer(1024);
            int recv = ssh_if.receive(&buffer[0], buffer.size(), terms);
            if(recv < 0)
            {
                break;
            }
            int sent = ssh_if.send(&buffer[0], static_cast<std::size_t>(recv), terms);
            if(sent < 0)
            {
                break;
            }
            assert(sent == recv);
        }
        std::cout << "connection loop finished" << std::endl;
    }
    catch(...)
    {
        std::cout << "connection loop finished with an exception" << std::endl;
        sync.set_error(boost::current_exception());
    }
}
